/**
 * 
 */
package com.google.code.joto.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.google.code.joto.CustomProcessor;
import com.google.code.joto.ReverseEngineerObject;
import com.google.code.joto.ReverseEngineerObjectResponse;

/**
 * @author Edu Pereda
 */
public class ClassCreatorHelper
{
    private static long scenaryNumber = System.currentTimeMillis();

    private final ReverseEngineerObject reverseEngineerObject;

    private final File outputSrcFolder;

    private final String outputPackageName;

    private final List<? extends CustomProcessor> userSuppliedProcessors;

    ClassCreatorHelper()
    {
        this.outputSrcFolder = new File( "." );
        this.outputPackageName = "";
        reverseEngineerObject = new ReverseEngineerObject();
        userSuppliedProcessors = new LinkedList<CustomProcessor>();
    }

    public ClassCreatorHelper( File outputSrcFolder, String outputPackageName,
                               List<? extends CustomProcessor> userSuppliedProcessors )
    {
        if ( !StringUtil.isJavaPackage( outputPackageName ) )
        {
            throw new IllegalArgumentException( "Not a valid java package name. outputPackageName: "
                + outputPackageName );
        }
        this.userSuppliedProcessors = userSuppliedProcessors == null ? new LinkedList<CustomProcessor>()
                                                                    : userSuppliedProcessors;
        this.outputSrcFolder = outputSrcFolder;
        this.outputPackageName = outputPackageName;
        reverseEngineerObject = new ReverseEngineerObject();
    }

    public File extractToDummyObject( Object objectToProcess, String classNamePrefix, String classNameSuffix )
        throws IOException
    {
        ReverseEngineerObjectResponse generatedCode = reverseEngineerObject.generateCode( objectToProcess,
                                                                                          userSuppliedProcessors );
        System.out.println( generatedCode );
        File parentFolder = StringUtil.packageNameToFile( this.outputSrcFolder, this.outputPackageName );
        parentFolder.mkdirs();

        String className = classNamePrefix + scenaryNumber++ + classNameSuffix;
        File autogeneratedClassFile = new File( parentFolder, className + ".java" );
        if ( !autogeneratedClassFile.exists() )
        {
            PrintStream out = new PrintStream( autogeneratedClassFile );
            out.println( "package " + this.outputPackageName + ";" );
            out.println( generatedCode.imports );
            out.println( "/** " );
            out.println( " * This class was automatically generated." );
            out.println( " */" );
            out.println( "class " + className + " {" );
            out.println( " public static " + objectToProcess.getClass().getSimpleName() + " createInstance() {" );
            out.println( " return (" );
            out.println( generatedCode.code );
            out.println( " );" );
            out.println( " }" );
            out.println( "}" );
            out.close();
            System.out.println( "autogeneratedClassFile: " + autogeneratedClassFile.getAbsolutePath() );
        }
        else
        {
            System.out.println( autogeneratedClassFile + " already exists. Ignoring" );
            BufferedWriter out = new BufferedWriter( new FileWriter( autogeneratedClassFile, true ) );
            out.append( "\n// Appending this line because file " );
            out.append( autogeneratedClassFile.getAbsolutePath() );
            out.append( " already existed. Current time is " );
            out.append( new Date().toString() );
            out.append( ".\n" );
        }
        return autogeneratedClassFile;
    }

    /**
     * @return the outputSrcFolder
     */
    public File getOutputSrcFolder()
    {
        return outputSrcFolder;
    }

    /**
     * @return the outputPackageName
     */
    public String getOutputPackageName()
    {
        return outputPackageName;
    }

}
